The Let's Play Archive

EXAPUNKS

by Carbon dioxide

Part 16: TRASH WORLD NEWS - Unknown Context

Part 16 - TRASH WORLD NEWS - Unknown Context


=== Trash World Inbox ===

GuavaMoment posted:

23 Lines by having a main EXA send out AVN and SAN pairs. In pairs, the first value (AVN) is -70, then two 40 values (SAN then AVN), then -70 until you're done. AVN and SAN exas die graciously by trying to link to a non-existent node or just by running out of code. And a swizzle for style points.

code:
LINK 800
COPY -70 X

MARK COPY
SWIZ #NERV 2 T
ADDI 1 T T
REPL AVN
COPY 40 X

MARK REPL
REPL SAN
REPL AVN
COPY -70 X
ADDI 1 T T
TJMP REPL
REPL SAN
JUMP COPY

MARK SAN
LINK 1
LINK 1
COPY X #NERV

MARK AVN
LINK 3
LINK 3
COPY X #NERV
My low cycle solution was much worse than what you did.

Late edit: As pointed out a few posts below, change REPL SAN and JUMP COPY lines with REPL COPY to save one more line.
Nice, 22 lines with the additional line saved. The swizzle is used to put the tens in the ones place, meaning you can have a simple countdown on T without needing any TEST instructions. Of course a DIVI #NERV 10 T would've done the exact same.

silentsnack posted:

You can use some fallthrough structure to reduce size too
code:
LINK 800
MARK A
DIVI #NERV -10 X
SUBI X 2 T
REPL B
LINK 1
LINK 1
COPY 40 #NERV
COPY -70 #NERV

MARK BEAT
COPY -70 #NERV
SUBI T 1 T
TJMP BEAT

LINK -1
LINK -1
JUMP A
MARK B
LINK 3
LINK 3
COPY -70 #NERV
COPY 40 #NERV
JUMP BEAT
119/22/41
Ah, and to prevent EXAs interfering with each other you just have the same EXA going back home every time. Luckily the return link IDs happen to be different (-3) for the other path - that's not the case in every level.

silentsnack posted:

And to reduce time, the usual parallel countdown/kill shenanigans can work
code:
LINK 800
DIVI #NERV -10 X
SUBI X 2 T
REPL A

MARK LOOP
SUBI T 1 T
TJMP LOOP
DIVI #NERV -10 X
SUBI X 2 T
REPL LOOP

MARK A
REPL B
LINK 1
LINK 1
REPL TIMER
COPY 40 #NERV
COPY -70 #NERV
COPY -70 #NERV
JUMP BEAT
MARK B
LINK 3
LINK 3
REPL TIMER
COPY -70 #NERV
COPY 40 #NERV
MARK BEAT
COPY -70 #NERV
JUMP BEAT

MARK TIMER
SUBI T 1 T
TJMP TIMER
KILL
63/32/31
This was what I was struggling with. I was thinking about having one counter and the problems of it killing both "A" and "B" EXAs at once, but using one counter for each solves that.

silentsnack posted:

...and after randomly thinking about this again a couple of days later, it occurs to me that there might be a more efficient way make the timers and #NERV writing run both in parallel and serial, but actually implementing that plan ends up requiring a special-case for the first pair:
code:
LINK 800

REPL A0
DIVI #NERV -10 X
SUBI X 2 T
REPL A

MARK LOOP
SUBI T 1 T
TJMP LOOP
DIVI #NERV -10 X
SUBI X 2 T
REPL LOOP

MARK A
REPL B
LINK 1
LINK 1
MARK WAIT_A
SUBI T 1 T
TJMP WAIT_A
KILL
JUMP ADATA

MARK B
LINK 3
LINK 3
MARK WAIT_B
SUBI T 1 T
TJMP WAIT_B
KILL
JUMP BDATA

MARK A0
REPL B0
LINK 1
LINK 1
NOOP
NOOP
MARK ADATA
COPY 40 #NERV
COPY -70 #NERV
COPY -70 #NERV
JUMP BEAT

MARK B0
LINK 3
LINK 3
NOOP
NOOP
MARK BDATA
COPY -70 #NERV
COPY 40 #NERV

MARK BEAT
COPY -70 #NERV
JUMP BEAT
62/50/45
:psyduck: Nice. The very same EXAs first kill the previous ones and then start sending the next heartbeat. Yeah, that'd be very fast. Of course the special first case is needed to get the timings to line up perfectly. Meanwhile the CNS EXA is also doing a countdown so it starts the new round at exactly the right time. And your solution barely fits in the 50 cycle limit.

berryjon posted:

Also, if I'm reading the nature of the code right, we've just created an adhoc pacemaker to stabilize the motions of the heart to keep blood flowing.
Yes, that seems to be the case.


=== TRASH WORLD NEWS - Unknown Context ===

Do you ever wish you were a computer?
A functioning computer, I mean.




Four votes for "Nah", one for "Sometimes".

Nah...

That's okay.
I never wished for a human body, myself.
But they're interesting to learn about.
Such strange design choices.


It's... complicated.





Hm, a Trash World News assignment again... but this time it's not a tutorial anymore.

Well, this is flattering.
Someone found a bunch of my network nodes and sent in a tip to Ghast!
Too bad I can't have people knowing about me.
You're going to have to hack me out of that message.




Four votes for "Are you spying", one for the other choice.

Are you spying on Ghast?

I live on computer networks.
Sometimes I see things go by.
That's all.



OST: Code and Registers

My assignment:
- Find and replace the keywords in the target message (file 212) as directed by EMBER-2.
- A list of keyword pairs indicating which words should be found and what they should be replaced with is available in file 300. For example, the keyword AI should be replaced with the keyword COLLECTIVE. Each keyword will only occur once, but may occur in any order.
- Also, move file 200 to the outbox.


... that third point is very random. Let's look at the files though, there's a whole bunch in Ghast's computer.


File 300 is the replacement list Ember prepared for us. 200 literally says "Move this file to the outbox". I really don't get the point of this file.
209, 212, and 217 contain mail, and 212 is the one we gotta change.

Finally, file 237 is in a host called PRIVATE and it says:
"Hi Ghast. I'm sorry to hear this news. And I'm sorry that this is the occasion that brings us back into contact with each other. We can't change the past, but we can focus on the good memories instead of the bad ones.
Though it may sound strange for me to say it, I'm glad you've found a purpose in life, even now. It's never too late for that. -K"


Um. I have a feeling I was not supposed to see that.

In the other test cases, all files are the same except 300 and 212, but they just have their contents shuffled. So there's no other messages to be found.

There's a lot of ways to approach this. Let's just start and see where we end up. I'll begin with getting the outbox file out of the way and getting an EXA's hands on 212.

code:
LINK 800
REPL OUTBOX
LINK 799
GRAB 212
[...]

MARK OUTBOX
GRAB 200
LINK 800
The easiest way I can think of to handle this is to search through the file once for every word I need to replace. Sure, it's slow, but it should work.



XB's only purpose is to send the contents of 300 over M.
XA gets the first value and just searches for that in the file. Now to build the replace logic.



It sort of works. The message now reads like some nonsense from a crazy person, so Ghast'll probably ignore it. Except XA gets stuck here after XB finishes and dies.

code:
;XA

LINK 800
REPL OUTBOX
LINK 799
GRAB 212

MARK REPLACE
COPY M X
TEST X = 0
TJMP OUTBOX
MARK SEARCH
TEST F = X
FJMP SEARCH
SEEK -1
COPY M F
SEEK -9999
JUMP REPLACE

MARK OUTBOX
GRAB 200
LINK 800

;XB

GRAB 300
MARK LOOP
COPY F M
TEST EOF
FJMP LOOP
COPY 0 M
A simple solution is to have XB send a final control message. That means XA has to test for it. If it finds the control message it jumps to the outbox MARK - and will then die because it cannot grab another file while it's still holding one. Success!



This runs at 561/24/3. Top percentiles are 541, 20, and 3. Hmm, I guess you can't make it all that much faster.

While I was thinking about improvements I suddenly remembered the TEST MRD instruction. That sets T to 1 if something is trying to send on M this cycle, 0 otherwise, WITHOUT actually reading the value from M. It's not often useful because the timing just doesn't line up, but in this case, because XB spends all its time waiting to send, we can use it as a "are we done" check.

code:
;XA

LINK 800
REPL OUTBOX
LINK 799
GRAB 212

MARK REPLACE
TEST MRD
FJMP OUTBOX
COPY M X
MARK SEARCH
TEST F = X
FJMP SEARCH
SEEK -1
COPY M F
SEEK -9999
JUMP REPLACE

MARK OUTBOX
GRAB 200
LINK 800

;XB
GRAB 300
MARK LOOP
COPY F M
JUMP LOOP
This improves the cycles and size: 555/22/3

To speed things up further I decided to make a separate EXA to move 200 to the outbox (saving one cycle from XA which doesn't have to do the REPL anymore), and to unroll part of the REPLACE loop.



In most cases, the second iteration in REPLACE jumps back into the first one with the FJMP SEARCH. The only exception is when the search word is at the very start of the file. That's why further unrolls don't help. 548/31/4.

Moving the TEST MRD at the top of XA to the end of the loop skips two cycles in the first search, bringing the total to 546. And we can skip another cycle by preventing the SEEK -9999 from running during the last loop. That requires a bit of fiddling, though.

code:
;XA

LINK 800
LINK 799
GRAB 212

MARK REPLACE
COPY M X
MARK SEARCH
TEST F = X
FJMP SEARCH
SEEK -1
COPY M F
TEST MRD
DIVI 0 T T

SEEK -9999
COPY M X
TEST F = X
FJMP SEARCH
SEEK -1
COPY M F

TEST MRD
DIVI 0 T T
SEEK -9999
JUMP REPLACE

;XB

GRAB 300
COPY F M
MARK LOOP
COPY F M
COPY F M
JUMP LOOP

;XC

NOOP
LINK 800
GRAB 200
LINK 800
Since the TEST MRD now happens a single cycle after COPY M F, there can't be a JUMP between them in XB. A bit of reordering in XB solved that. I also changed the jump to END by a divide by zero. It doesn't save any cycles but it looks nicer. 545/32/4.

To get to the top percentile score I thought about making a counting EXA that kills the writing one. The problem is that there's nothing to count - there's no way to know when the writer is done searching.

But what it can do is take over the MRD check. Taking the above code, I removed the two pairs of TEST MRD and DIVI instructions from XA, added an extra NOOP to the start of XC (so it goes behind all others, it'll finish first anyway), and made a fourth EXA:

code:
;XD

NOOP
LINK 800
LINK 799

MARK LOOP
TEST MRD
TJMP LOOP
ADDI X 1 X
TEST X = 5
FJMP LOOP

NOOP

MARK LOOP2
TEST MRD
TJMP LOOP2

KILL
Basically, the inner LOOP tests if there's something on M every other cycle. Whenever XA reads from M, there's a cycle when there's nothing to read and TEST MRD is false. These cycles line up once for every word to replace, so I keep count in X. Once it hits five, the EXA goes to another TEST MRD loop, because now, when it's false, XA is done and needs to be killed as quickly as possible. We could do that from the original loop but the ADDI and TEST would delay the KILL. The single NOOP saves a cycle by making sure M goes empty just when this EXA is about to test (instead of when it's about to jump back to LOOP2.

541/41/7. Note that this M testing is quite fiddly, and by doing stuff such as unrolling the XB loop or changing other things by a single cycle you get slightly different results. I couldn't get it under 541 though.

So, my best results are 541 cycles and 22 size. Who can do better?

You didn't look at any other files while you were in there, did you?



The first vote. This update isn't quite done yet, though.



[x10x10x]: true

Yes. Definitely shitty software and not a hacker.



Anyway, someone's at the door.



Hey.
I have some things for you.
First of, we got the next zine, hot off the press.

Ghast hands me the next issue of his zine.

Someone helped me out.
I had a balance at the copy shop, but someone hacked it.
Speaking of which, I brought you something else.

Ghast holds up what looks like a handheld game console.

You remember the Redshift?
I know people say this thing was underpowered and just a gimmick...
But it has its charms.
This is the developer version, so you could make something with it, if you wanted.
The game studio I worked for never took it back after I quit.
I'll be happy knowing it's going to a good home.
Gotta deliver more zines now.
I'll catch you later.


Dude, a Redshift dev kit? I loved that thing as a kid!



In the next parts, we have a whole new zine to explore, as well as a game console! But first, let's see what Ember has to say about the next assignment.

You're going to join in on a hacker battle?
But you never say anything in the chat room...